-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
expression: round function for int should use round half up rule #27403
base: master
Are you sure you want to change the base?
Conversation
[REVIEW NOTIFICATION] This pull request has not been approved. To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by submitting an approval review. |
but i met some problem and had been blocked a few days, so i need help from you. i fingerd out the test is blocked by the last commit if i revert it, the test will not block.
now i am blocked and don't know how to continue, please help. |
expression/integration_test.go
Outdated
// MySQL 8 will report an error if round result overflows | ||
rs, err = tk.Exec("select round(18446744073709551615, -19);") | ||
c.Assert(err, NotNil) | ||
terr = errors.Cause(err).(*terror.Error) | ||
c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrDataOutOfRange)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[2021-08-19T15:56:19.448Z] FAIL: integration_test.go:413: testIntegrationSuite2.TestMathBuiltin
[2021-08-19T15:56:19.448Z]
[2021-08-19T15:56:19.448Z] integration_test.go:705:
[2021-08-19T15:56:19.448Z] c.Assert(err, NotNil)
[2021-08-19T15:56:19.448Z] ... value = nil
tests failed by above. I think you can take a look at "// for pow" part to see how to validate errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rs, err = tk.Exec("SELECT POW(0, -1);")
c.Assert(err, IsNil)
_, err = session.GetRows4Test(ctx, tk.Se, rs)
c.Assert(err, NotNil)
terr = errors.Cause(err).(*terror.Error)
c.Assert(terr.Code(), Equals, errors.ErrCode(mysql.ErrDataOutOfRange))
c.Assert(rs.Close(), IsNil)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[2021-08-19T15:56:19.448Z] FAIL: integration_test.go:413: testIntegrationSuite2.TestMathBuiltin [2021-08-19T15:56:19.448Z] [2021-08-19T15:56:19.448Z] integration_test.go:705: [2021-08-19T15:56:19.448Z] c.Assert(err, NotNil) [2021-08-19T15:56:19.448Z] ... value = nil
tests failed by above. I think you can take a look at "// for pow" part to see how to validate errors.
thanks.
i learned validate error like above from the other tidb test files. i will investigate to learn more.
sorry and can't image the log clearly show why it fails but i did not notice..
I need be more careful..
if math.IsNaN(result) { | ||
return 0 | ||
} | ||
return result | ||
} | ||
|
||
// RoundInt rounds the argument i to dec decimal places using "round half up" rule. | ||
// dec defaults to 0 if not specified. dec can be negative | ||
func RoundInt(i int64, dec int) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider unsigned int range and overflow.
MySQL [test]> select round(9223372036854775808,-3);
+-------------------------------+
| round(9223372036854775808,-3) |
+-------------------------------+
| 9223372036854776000 |
+-------------------------------+
1 row in set (0.000 sec)
MySQL [test]>
MySQL [test]> select round(-9223372036854775808,-3);
ERROR 1690 (22003): BIGINT value is out of range in 'round(-(9223372036854775808),-(3))'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for suggestion, i will check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
select round(1234567890123456789012345678901234567890, -30);
# output: 1234567890000000000000000000000000000000
i found both mysql 8
and tidb v5.1.1
have above result,
and 1234567890123456789012345678901234567890
is clearly much larger than math.MaxInt64
,
so it cloud not be the param or return value of builtinRoundWithFracIntSig.evalInt
,
i believe above case and unsigned int should have processed in some other place,
so i will not process these case in roundInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so.
select round(1234567890123456789012345678901234567890, -30); This case is decimal round, not int.
We can create a table with bigint field and insert -9223372036854775808
, then round it should throw the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can try to port mysql's logic https://github.com/mysql/mysql-server/blob/beb865a960b9a8a16cf999c323e46c5b0c67f21f/sql/item_func.cc#L3413
8ca8620
to
09fc30f
Compare
09fc30f
to
0f088e6
Compare
/run-check_dev_2 |
1 similar comment
/run-check_dev_2 |
cc @riteme since you have already finished this tough work in TiFlash. |
/run-check_dev_2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you deal with unsigned integer round? I see there's two versions of abs
for integers: one for int64
and another for uint64
.
tidb/expression/builtin_math.go
Lines 67 to 70 in 22034c5
_ builtinFunc = &builtinAbsRealSig{} | |
_ builtinFunc = &builtinAbsIntSig{} | |
_ builtinFunc = &builtinAbsUIntSig{} | |
_ builtinFunc = &builtinAbsDecSig{} |
@feitian124 you can try to find the failure cause by downloading the log and match patterns listed here https://pingcap.github.io/tidb-dev-guide/get-started/write-and-run-unit-tests.html#how-to-find-the-failed-tests |
current fix did not include change for unsigned integer , see above discuss with @wshwsh12 this fix is not perfect, but should have resolved the orignial issue which is caused by large number issue like unsigned integer and decimial which is out range of int64, it should be another problem so i wonder if this pr can be merged first for 2 reason:
|
ok, thanks. |
} | ||
|
||
shift := math.Pow10(-dec) | ||
intPart := math.Round(float64(i) / shift) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test case.
MySQL [test]> select round(24999999999999999,-16);
+------------------------------+
| round(24999999999999999,-16) |
+------------------------------+
| 20000000000000000 |
+------------------------------+
1 row in set (0.000 sec)
We should avoid float calc in int round.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added and failed, will fix later
/uncc I may not be the reviewer to this PR. And it seems there is already reviewers work on this. |
@feitian124: PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
What problem does this PR solve?
Issue Number: close #26993, close #27128
Problem Summary:
this pr aims to solve #26993 use suggestion from pr #27128. pr #27128 is deprecated and can be close by this pr too.
What's Changed:
RoundFloat
by usingmath.RoundToEven
directlyfunc RoundInt(i int64, dec int) int64
to round intfunc Round(f float64, dec int) float64
tofunc RoundFloat(f float64, dec int) float64
to make name consistent withRoundInt
Tests
Release note